package com.lagou.client;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 最快响应负载均衡策略实现
 */
@Slf4j
public class FastBalanceStrategy {
    public static RpcConsumer getConsumer() {
        // 获取当前连接列表
        List<RpcConsumer> consumers = ConnectionManager.getManager().getConsumers();
        if (!consumers.isEmpty()) {
            // 获取最后响应时间为0的
            List<RpcConsumer> freeConsumers = consumers.stream()
                    .filter(c -> c.getServerInfo().getLastAckSpeed() == 0)
                    .collect(Collectors.toList());
            // 获取最后更新速度时间超过5秒的连接
            List<RpcConsumer> maximumTime = consumers.stream()
                    .filter(c -> (System.currentTimeMillis() - c.getServerInfo().getLastAckTime()) > 5000)
                    .collect(Collectors.toList());

            if (!freeConsumers.isEmpty()) {
                RpcConsumer consumer = freeConsumers.get(new Random().nextInt(freeConsumers.size()));
                log.info("------------------------触发为响应时间为0条件，表示初次使用------------------------------");
                log.info("为0的链接，未被使用过的[{}] 响应时间[{}] 最后更新时间[{}]",
                        consumer.getServerInfo().getServerName(),
                        consumer.getServerInfo().getLastAckSpeed(),
                        DateUtil.date(consumer.getServerInfo().getLastAckTime()),
                        System.currentTimeMillis() - consumer.getServerInfo().getLastAckTime()
                );
                return consumer;
            } else if (!maximumTime.isEmpty()) {
                RpcConsumer consumer = maximumTime.get(new Random().nextInt(maximumTime.size()));
                log.info("------------------------触发5秒未使用条件------------------------------");
                log.info("超过5秒未使用的链接[{}] 响应时间[{}] 最后更新时间[{}]",
                        consumer.getServerInfo().getServerName(),
                        consumer.getServerInfo().getLastAckSpeed(),
                        DateUtil.date(consumer.getServerInfo().getLastAckTime()),
                        System.currentTimeMillis() - consumer.getServerInfo().getLastAckTime()
                );
                return consumer;
            } else {
                // 如果归0集合为空，则对所有连接按响应时间排序，并取首位
                // 需求中如果响应时间相同则取随机，应该没有必要，如果最小的两个相同，取第一个发送后，响应时间就会重新计算
                consumers.sort((c1, c2) -> (int) (c1.getServerInfo().getLastAckSpeed() - c2.getServerInfo().getLastAckSpeed()));
                RpcConsumer consumer = consumers.get(0);

                // 打印选择过程
                log.info("选择上次响应时间最快连接[{}] => [{}]",
                        consumer.getServerInfo().getServerName(),
                        StringUtils.collectionToDelimitedString(consumers.stream().map(c -> String.format("%s:%d", c.getServerInfo().getServerName(),
                                c.getServerInfo().getLastAckSpeed())).collect(Collectors.toList()),
                                ","
                        )
                );
                return consumer;
            }
        }
        return null;
    }
}
